package ca.jsbr.as2js_lib.display.canvas.view 
{
	import ca.jsbr.as2js_lib.display.canvas.CanvasStage;
	import ca.jsbr.as2js_lib.display.canvas.StageDescription;
	import ca.jsbr.as2js_lib.event.RequestEvent;
	import ca.jsbr.as2js_lib.utils.DataLoader;
	import ca.jsbr.as2js_lib.utils.geom.Rect;
	import flash.events.Event;
	import flash.utils.Dictionary;
	import js.element.canvas.CanvasRenderingContext2D;
	/**
	 * ...
	 * TODO Subdivise json and default?
	 * @author jsbr [me@jsbr.ca]
	 */
	public class SpriteView extends Image 
	{
		private var _col:int = 1;
		private var _row:int = 1;
		
		private var _anim:Dictionary;
		private var _currentPlay:String = "__all__";
		private var _current:int;
		private var _currentDelta:Number;
		private var _loader:DataLoader;
		private var _json:Object;
		private var _fps:int;
		/**
		 * 
		 * @param	src	source of sprite (can be: image tag, json object, path to ".json" or "image" file)
		 * @param	col
		 * @param	row
		 */
		public function SpriteView(src:*=null,col:int=1,row:int=1) 
		{
			_anim = new Dictionary();
			super(src);
			_fps = CanvasStage.instance.stageDescription.fps;
			setAnimationSize(col, row);
			
		}
		
		/**
		 * 
		 * @param	src	source of sprite (can be: image tag, json object, path to ".json" or "image" file)
		 * @return
		 */
		override public function addSrc(src:*):void 
		{
			if (!src)
				return;
			if (typeof(src)=="string" && src.indexOf(".json"))
			{
				_loader = new DataLoader();
				_loader.addEventListener(RequestEvent.COMPLETE, onLoadJsonComplete);
				_loader.load(src);
			}
			else if (src.image)
			{
				applyJson(src);
			}
			else
			{
				super.addSrc(src);
			}
			
		}
		
		override protected function onLoad(e:Event):void 
		{
			_ready = true;
			if (_json)
			{
				if(_width==0)
					_width = _json.frames[0].w;
				if(_height==0)
					_height = _json.frames[0].h;
			}
			else
			{
				if(_width==0)
					_width = _image.width/_col;
				if(_height==0)
					_height = _image.height / _row;
			}	
			_srcWidth = _image.width;
			_srcHeight = _image.height;
		}
		
		
		
		private function onLoadJsonComplete(e:RequestEvent):void 
		{
			applyJson(_loader.getJSON());
		}
		
		private function applyJson(json:Object):void
		{
			_json = json;
			
			for (key in _json.define)
			{
				defineAnimation(key,_json.define[key][0],_json.define[key][1]);
			}
			if(_json.fps)
				_fps = _json.fps;
			
			defineAnimation("__all__",0,_json.frames.length-1);
			super.addSrc(_json.image);
			_width = _json.frames[0].w;
			_height = _json.frames[0].h;
		}
		
		/**
		 * 
		 * @param	name
		 */
		public function play(name:String=null):void
		{
			if(name)
				_currentPlay=name;
			else
				_currentPlay="__all__";
		}
		
		public function stop():void
		{
			_currentPlay=null;
		}
		
		public function gotoFrame(frame:int):void
		{
			_current = frame;
		}
		
		public function setAnimationSize(col:int,row:int):void
		{
			_col = col;
			_row = row;
			if (!_json && _ready)
			{
				_width = _srcWidth  /_col;
				_height = _srcHeight/ _row;
			}	
			defineAnimation("__all__", 0, col * row);
		}
		
		public function defineAnimation(name:String,startFrame:int,endFrame:int):void
		{
			_anim[name] = [startFrame, endFrame-startFrame];
		}
		
		override public function get width():Number 
		{
			return _width;
		}
		
		override public function set width(value:Number):void 
		{
			_width = value;
		}
		
		override public function get height():Number 
		{
			return _height;
		}
		
		override public function set height(value:Number):void 
		{
			_height = value;
		}
		
		public function get json():Object 
		{
			return _json;
		}
		
		public function set json(value:Object):void 
		{
			_json = value;
		}
		
		public function get currentPlay():String 
		{
			return _currentPlay;
		}
		
		override public function render(context:CanvasRenderingContext2D):void 
		{
			if (_ready)
			{
				//Current Frame
				var frame:int = _current;
				if (_currentPlay)
				{
					var frame:int;
					if (_fps != CanvasStage.instance.stageDescription.fps || CanvasStage.instance.stageDescription.repaintMode == StageDescription.REPAINT_BROWSER){
						_currentDelta += CanvasStage.instance.frameDelta*0.001 * _fps;
						_current = _currentDelta >> 0;
						frame = _current;
					}
					else{
						frame =++_current;
					}
					frame %= _anim[_currentPlay][1];
					frame += _anim[_currentPlay][0];
					/*if (frame == _anim[_currentPlay][0]) {
						_currentDelta = 1;
						_current = 0;
					}*/
				}
				
				if (_json)
					renderJSON(frame, context);
				else
					renderDefault(frame, context);
			}
		}
		
		private function renderJSON(frame:int,context:CanvasRenderingContext2D):void
		{
			var w:Number=_json.frames[frame].w;
			var h:Number=_json.frames[frame].h;
			var px:Number=_json.frames[frame].x;
			var py:Number = _json.frames[frame].y;
			_width = w;
			_height = h;
			context.drawImage(_image, px, py, w, h, stageX, stageY, _width, _height);
		}
		
		private function renderDefault(frame:int,context:CanvasRenderingContext2D):void
		{
			var w:Number=_width;
			var h:Number=_height;
			context.drawImage(_image, (frame % _col) * w, Math.floor(frame / this._col) * h, w, h, stageX, stageY, _width, _height);
		}
		
		override public function clone():SpriteView 
		{
			var img:SpriteView = new SpriteView();
			img.json = _json;
			img.setAnimationSize(_col, _row);
			img.x = x;
			img.y = y;
			
			for (var ind:String in _anim)
			{
				img.defineAnimation(ind, _anim[ind][0], _anim[ind][0]+_anim[ind][1]);
			}
			img.image = _image;
			img.json = _json;
			if (_currentPlay)
				img.play(_currentPlay)
			return img;
		}		
	}

}